package com.ie.cloud.payment.config;

import com.ie.cloud.payment.cache.RedisUtil;
import com.ie.cloud.payment.constants.CS;
import com.ie.cloud.payment.exception.MD5Exception;
import com.ie.cloud.payment.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.impl.InvalidContentTypeException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.naming.AuthenticationException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;

/**
 * Created with FR
 *
 * @Author: DQ
 * @Date: 2025/07/21/14:29
 * @Description: 描述语句
 */
@Component
@Slf4j
public class VerifyUtils {


    public static final String Authorization = "Authorization";

    public static final String Content_MD5 = "Content-MD5";

    public static final String Content_Type = "Content-Type";

    public static final String Date = "Date";

    @Resource
    private AppSecurity appSecurity;


    /**
     * 校验1
     */
    public boolean verifyV1(HttpServletRequest request, HttpServletResponse response, Object handler)  throws Exception{
        Object verifySwitch = RedisUtil.getObject(CS.VERIFY_SWITCH);

        if (verifySwitch == null || verifySwitch.equals(Boolean.FALSE.toString())) {
            log.info("未开启验证");
            return true;
        }




//        白名单
        String pathInfo = request.getRequestURI();
        if (new ArrayList<>(Arrays.asList("/ie-payment/api/callback/call")).contains(pathInfo)) {
            log.info("白名单");
            return true;
        }


        log.info("开始验证");

        String authToken = request.getHeader(Authorization);
        String conString = request.getHeader(Content_MD5);

        String contentType = request.getHeader(Content_Type);
        String DateString = request.getHeader(Date);
        if (StringUtils.isEmpty(conString)) {
            throw new MD5Exception();
        }
        if (StringUtils.isEmpty(contentType)) {
            throw new InvalidContentTypeException();
        }


        if(StringUtils.isEmpty(authToken)){
            throw new AuthenticationException();
        }

//        if (StringUtils.isEmpty(DateString)) {
//            throw new BizException(BizStatus.NOT_DATE_FOUNT);
//        }


        //Authorization:  API 1300386381676644416:N02s7Zy+RIW63m2hyniy/xq6n2c=
        //解析authToken得到apiSecret和appId

        String[] split = authToken.split(":");

        if (split.length != 2){
            throw new AuthenticationException();
        }

//        if (Math.abs(ChronoUnit.MILLIS.between(getGMTLocalDateTime(DateString), LocalDateTime.now())) > 15 * 60 * 1000) {
//            throw new BizException(BizStatus.TIME_STAMP_CREATION_TIMEOUT);
//        }

        //暂不知道 apiSecret 是如何加密,使用appId匹配
        String signOther = split[1];//外部签名


        //app生成签名:   apiSecret,POST+ "\n"
        //+ Content-MD5 + "\n" + Content-Type + "\n" + Date+ "\n"
        //+ CanonicalizedResource
        String elements = new StringBuilder()
                .append(request.getMethod())
                .append("\n")
                .append(conString)
                .append("\n")
                .append(contentType)
                .append("\n")
//                .append(DateString)
//                .append("\n")
                .append(request.getRequestURI())
                .toString();
        log.info("待签名的要素 \n{}",elements);
        Base64.Encoder encoder = Base64.getEncoder();
        String sign = encoder.encodeToString(HmacUtils.hmacSha1(appSecurity.getAppSecret().getBytes(), elements.getBytes()));


        log.info("平台 Base64 编码后的 签名值 {}",sign);
        log.info("待比较的签名值 {}",signOther);
        if (sign.equals(signOther)){

            return true;
        }else {
            throw new AuthenticationException();
        }

    }

    public static String getDigest(String context) {
        String result = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(context.getBytes());
            byte[] b = md.digest();
            Base64.Encoder encoder = Base64.getEncoder();
            result = encoder.encodeToString(b);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getDigestE(String context) {
        String result = "";
        try {
            Base64.Decoder encoder = Base64.getDecoder();

            byte[] decode = encoder.decode(context);
            result = new String(decode, StandardCharsets.UTF_8);
        } catch (IllegalArgumentException e) {
            throw e;
        }
        return result;
    }



    public static LocalDateTime getGMTLocalDateTime(String s) {
        try {
            if (s == null){
                return null;
            }
            Calendar calendar = DateUtils.gmtToCalendar(s);

            java.util.Date time = calendar.getTime();

            return time.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        }catch (Exception e) {
            throw e;
        }

    }
}
